﻿using ProjectFootball.MVC.Areas.TeamArea.Models;
using ProjectFootball.MVC.Foundation;
using ProjectFootball.MVC.Foundation.ResourceLibrary;
using ProjectFootball.MVC.Models.EntityFramework.Entities;
using ProjectFootball.MVC.Models.RepositoryProviders;
using System;
using System.Linq;
using System.Security.Principal;
using System.Web.Mvc;

namespace ProjectFootball.MVC.Areas.TeamArea.Controllers
{
    [Authorize]
    public class EditorController : BaseController
    {
        #region Constructor
        public EditorController(IRepositoryProvider provider)
            :base(provider)
        {
        }
        #endregion

        #region /TeamArea/Editor
        public ActionResult Index(Guid id)
        {
            var teamVersion = Provider.TeamVersionRepository.SearchByPrimaryKey(id);

            if (teamVersion == null)
                return RedirectHome;

            var teamViewModel = teamVersion.GetTeamViewModel(User, SearchType.Details);
            teamViewModel.TeamDataModel = teamVersion.GetDataModel();
            teamViewModel.TeamDataModel.EditorDbType = teamVersion.GetEditorDbTypeForEdit(User);

            return View(teamViewModel);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(TeamDataModel teamDataModel)
        {
            var teamVersion = Provider.TeamVersionRepository.SearchByPrimaryKey(teamDataModel.TeamVersionGuid);
            var teamViewModel = teamVersion.GetTeamViewModel(User, SearchType.Details);
            teamViewModel.TeamDataModel = teamDataModel;

            if (!ModelState.IsValid)
                return View(teamDataModel);

            if (teamVersion.CanEdit(User))
            {
                teamVersion.Edit(teamDataModel, User);
                SetEditDbType(teamVersion);
            }
            else
            {
                teamVersion = teamDataModel.CreateNew(User, CreateType.Unapproved);
                Provider.TeamVersionRepository.Add(teamVersion);
                SetCreateDbType(teamVersion);
            }

            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = teamVersion.Pk });
        }
        #endregion

        #region /TeamArea/Editor/CreateNew
        public ActionResult CreateNew()
        {
            var teamViewModel = new TeamViewModel()
            {
                TeamDataModel = new TeamDataModel()
                {
                    EditorDbType = User.IsApprover() ? DbType.CreatedPublic : DbType.CreatedPrivate
                }
            };

            return View("Index", teamViewModel);
        }
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateNew(TeamDataModel teamDataModel)
        {
            if (!ModelState.IsValid)
                return View("Index", new TeamViewModel() { TeamDataModel = teamDataModel });

            var createType = User.IsApprover() ? CreateType.Public : CreateType.Private;
            
            var team = new Team();
            team.TeamGuid = Guid.NewGuid();
            var teamVersion = teamDataModel.CreateNew(User, createType);
            teamVersion.TeamGuid = team.TeamGuid;

            if (teamVersion.CountryGuid != null)
                teamVersion.Country = Provider.CountryRepository.SearchByPrimaryKey(teamVersion.CountryGuid);

            Provider.TeamRepository.Add(team);
            Provider.TeamVersionRepository.Add(teamVersion);

            Provider.SaveChanges();

            SetCreateDbType(teamVersion);

            return RedirectToAction("Index", "Details", new { id = teamVersion.Pk });
        }
        #endregion

        #region /TeamArea/Editor/CreateVersion
        public ActionResult CreateVersion(Guid id)
        {
            var teamVersion = Provider.TeamVersionRepository.SearchByPrimaryKey(id);

            if (teamVersion == null)
                return RedirectHome;

            var teamDataModel = teamVersion.GetDataModel();
            teamDataModel.TeamVersionGuid = Guid.NewGuid();
            teamDataModel.ApprovalGuid = Guid.NewGuid();

            var teamViewModel = new TeamViewModel(){ TeamDataModel = teamDataModel };
            teamViewModel.TeamDataModel.EditorDbType = User.IsApprover() ? DbType.CreatedPublic : teamVersion.IsPublic ? DbType.CreatedUnapproved : DbType.CreatedPrivate;

            return View("Index", teamViewModel);
        }
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateVersion(TeamDataModel teamDataModel)
        {
            var teamVersions = Provider.TeamVersionRepository.Where(t => t.TeamGuid == teamDataModel.TeamGuid && !t.IsMarkedForDeletion);

            foreach (var item in Provider.TeamVersionRepository.Where(t => t.TeamGuid == teamDataModel.TeamGuid && !t.IsMarkedForDeletion))
            {
                if (teamDataModel.ActiveTo > item.ActiveFrom && item.ActiveTo > teamDataModel.ActiveFrom)
                {
                    ModelState.AddModelError("ActiveFrom", "Active dates can't overlap other versions of this team");
                    ModelState.AddModelError("ActiveTo", "Active dates can't overlap other versions of this team");
                    var teamViewModel = new TeamViewModel() { TeamDataModel = teamDataModel };
                    teamViewModel.TeamDataModel.EditorDbType = User.IsApprover() ? DbType.CreatedPublic : teamVersions.FirstOrDefault().IsPublic ? DbType.CreatedUnapproved : DbType.CreatedPrivate;
                    return View("Index", teamViewModel);
                }
            }

            var createType = User.IsApprover() ? CreateType.Public : CreateType.Private;

            var newTeamVersion = teamDataModel.CreateNew(User, createType);
            Provider.TeamVersionRepository.Add(newTeamVersion);

            SetCreateDbType(newTeamVersion);

            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = newTeamVersion.Pk });
        }
        #endregion

        #region /TeamArea/Editor/Delete
        public ActionResult Delete(Guid id)
        {
            var teamVersion = Provider.TeamVersionRepository.SearchByPrimaryKey(id);

            if ( teamVersion == null || !teamVersion.CanDelete(User))
                return RedirectHome;

            Guid teamGuid = teamVersion.TeamGuid;

            teamVersion.MarkForDeletion();
            SetDbType(DbType.MarkedForDeletion);
            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = teamVersion.Pk });
        }
        #endregion

        #region /TeamArea/Editor/RecordForApproval
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult RecordForApproval(Guid id)
        {
            var teamVersion = Provider.TeamVersionRepository.Where(c => c.Pk == id).Single();
            var teamVersions = Provider.TeamVersionRepository.Where(c => c.ApprovalGuid == teamVersion.ApprovalGuid);
            var teamVersionsSummaryViewModels = teamVersions.Search(User, SearchType.RecordForApproval);

            return View(teamVersionsSummaryViewModels);
        }
        #endregion

        #region /TeamArea/Editor/ConfirmApproval
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult ConfirmApproval(Guid id)
        {
            if (!User.IsApprover())
                return View(false);

            TeamVersion teamVersion = Provider.TeamVersionRepository.Where(c => c.Pk == id).Single();

            var teamVersionQuery = from t in Provider.TeamVersionRepository.Where(c => c.ApprovalGuid == teamVersion.ApprovalGuid && c.IsApproved)
                                   select t;

            Guid approvedTeamVersionGuid;

            if (teamVersionQuery.Any())
            {
                TeamVersion approvedTeamVersion = teamVersionQuery.Single();
                approvedTeamVersionGuid = approvedTeamVersion.Pk;
                teamVersion.Approve(approvedTeamVersion);

                Provider.SaveChanges();
            }
            else
            {
                teamVersion.IsApproved = true;
                approvedTeamVersionGuid = teamVersion.Pk;
                Provider.SaveChanges();
            }

            IQueryable<TeamVersion> teamVersions = Provider.TeamVersionRepository.Where(c => c.ApprovalGuid == teamVersion.ApprovalGuid && !c.IsApproved);
            Provider.TeamVersionRepository.RemoveAll(teamVersions);

            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = approvedTeamVersionGuid });
        }
        #endregion

        #region TeamArea/Editor/PendingApprovals
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult PendingApprovals()
        {
            var teamVersions = Provider.TeamVersionRepository.Where(c => c.IsApproved == false);

            return View(teamVersions.Search(User, SearchType.PendingApprovals));
        }
        #endregion
    }
}
